package com.cgs.query.monitor.metrics

import com.cgs.query.util.Utils
import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.Metrics
import io.micrometer.core.instrument.Timer
import java.io.Serializable
import java.util.concurrent.TimeUnit

enum class MetricsHelper {

    INSTANCE;

    val registry: MeterRegistry = QueryMeterRegistry()

    init {
        Metrics.addRegistry(registry)
    }

    fun getProjectTimer(projectName: String): List<ProjectTimerInfo>? {
        return registry.find("server").tag("project", projectName).timers().mapNotNull {
            timer2ProjectTimerInfo(it)
        }
    }

    fun getServerTimer(): ServerTimerInfo? {
        var sum = 0L
        var fail = 0L
        registry.find("server").timers().forEach {
            sum += it.count()
            if (it is QueryMeterRegistry.TimerWrapper) {
                fail += it.fCount.get()
            }
        }
        return ServerTimerInfo(sum, fail)
    }

    private fun timer2ProjectTimerInfo(timer: Timer): ProjectTimerInfo? {
        return if (timer is QueryMeterRegistry.TimerWrapper) {
            timer.toProjectTimerInfo()
        } else {
            Utils.notNullAndConsume(timer.id.getTag("callName")) {
                ProjectTimerInfo(it, null, timer.count(), null,
                        "${timer.mean(TimeUnit.MILLISECONDS).toInt()} ms",
                        "${timer.max(TimeUnit.MILLISECONDS).toInt()} ms")
            }
        }
    }
}


/**
 * 项目sql Timer meter 信息
 */
class ProjectTimerInfo(
        /**调用名称*/
        val callName: String,
        /**最后执行时间*/
        val lastTime: Long?,
        /**总调用次数*/
        val count: Long,
        /**失败调用次数*/
        val fCount: Long?,
        /**平均执行时间*/
        val mean: String,
        /**最慢执行时间*/
        val maxCost: String) : Serializable {
}

/**
 * Server Timer 信息
 */
class ServerTimerInfo(
        /**总调用次数*/
        val count: Long,
        /**失败调用次数*/
        val fCount: Long?
) : Serializable